# -*- coding:utf-8 -*-
import pygame as 游戏
import sys as 系统
import random as 随机

# 全局定义

界面宽度 = 600
界面高度 = 600
像素大小 = 12

def 升级(等级):
    global 像素大小
    像素大小=10+2*等级

class 蛇类(object):
    # 初始化各种需要的属性 [开始时默认向右/身体块x5]
    def __init__(self):
        self.方向 = 游戏.K_RIGHT
        self.蛇身 = []
        for x in range(5):
            self.增加节点()
        
    def 增加节点(self):
        left,top = (0,0)
        if self.蛇身:
            left,top = (self.蛇身[0].left,self.蛇身[0].top)
        节点 = 游戏.Rect(left-left%像素大小,top-top%像素大小,像素大小,像素大小)
        if self.方向 == 游戏.K_LEFT:
            节点.left -= 像素大小
        elif self.方向 == 游戏.K_RIGHT:
            节点.left += 像素大小
        elif self.方向 == 游戏.K_UP:
            节点.top -= 像素大小
        elif self.方向 == 游戏.K_DOWN:
            节点.top += 像素大小
        self.蛇身.insert(0,节点)
        

    def 移除节点(self):
        self.蛇身.pop()
        

    def 是否死亡(self):
        # 撞墙
        if self.蛇身[0].x  not in range(界面宽度):
            return True
        if self.蛇身[0].y  not in range(界面高度):
            return True
        # 撞自己
        if self.蛇身[0] in self.蛇身[1:]:
            return True
        return False
        
    # 移动！
    def 移动(self):
        self.增加节点()
        self.移除节点()
        
    # 改变方向 但是左右、上下不能被逆向改变
    def 转向(self,当前按键):
        LR = [游戏.K_LEFT,游戏.K_RIGHT]
        UD = [游戏.K_UP,游戏.K_DOWN]
        if 当前按键 in LR+UD:
            if (当前按键 in LR) and (self.方向 in LR):
                return
            if (当前按键 in UD) and (self.方向 in UD):
                return
            self.方向 = 当前按键

    def 自动转向(self,目标点):
        left,top = (self.蛇身[0].left,self.蛇身[0].top)
        LR = [游戏.K_LEFT,游戏.K_RIGHT]
        UD = [游戏.K_UP,游戏.K_DOWN]
        if (目标点.top < self.蛇身[0].top) and (self.方向 in LR):
            预测点 = 游戏.Rect(left,top-像素大小,像素大小,像素大小)
            if not 预测点 in self.蛇身:
                self.方向 = 游戏.K_UP
                return
        if (目标点.top > self.蛇身[0].top) and (self.方向 in LR):
            预测点 = 游戏.Rect(left,top+像素大小,像素大小,像素大小)
            if not 预测点 in self.蛇身:
                self.方向 = 游戏.K_DOWN
                return
        if (目标点.left < self.蛇身[0].left) and (self.方向 in UD):
            预测点 = 游戏.Rect(left-像素大小,top,像素大小,像素大小)
            if not 预测点 in self.蛇身:
                self.方向 = 游戏.K_LEFT
                return
        if (目标点.left > self.蛇身[0].left) and (self.方向 in UD):
            预测点 = 游戏.Rect(left+像素大小,top,像素大小,像素大小)
            if not 预测点 in self.蛇身:
                self.方向 = 游戏.K_RIGHT
                return
       
class 食物类:
    def __init__(self):
        self.区域 = 游戏.Rect(-像素大小,0,像素大小,像素大小)
        
    def 移除(self):
        self.区域.x=-像素大小
    
    def 生成(self):
        if self.区域.x == -像素大小:
            全部坐标 = []
            # 不靠墙太近 像素大小 ~ SCREEN_X-像素大小 之间
            for pos in range(像素大小*3,界面宽度-像素大小*3,像素大小):
                全部坐标.append(pos)
            self.区域.left = 随机.choice(全部坐标)
            self.区域.top  = 随机.choice(全部坐标)
            # print(self.区域)
            
    def 刷新(self):
        # if self.区域.x>0:
            left,top = (self.区域.left,self.区域.top)
            self.区域 = 游戏.Rect(left-left%像素大小,top-top%像素大小,像素大小,像素大小)


class 目标点类:
    def __init__(self):
        self.区域 = 游戏.Rect(-像素大小,0,像素大小,像素大小)
    def 生成(self,x,y):
        self.区域 = 游戏.Rect(x-x%像素大小,y-y%像素大小,像素大小,像素大小)
    def 移除(self):
        self.区域.x=-像素大小
        
def 可用字体(系统字体):
    for 字体 in 系统字体:
        if 字体.find("yahei")>0:
            return 字体

def 显示文本(屏幕, 坐标, 文本, 颜色, 是否加粗 = False, 字号 = 60, 是否斜体 = False,字体="microsoftyaheimicrosoftyaheiui"):   
    # 设置字体 = 游戏.font.SysFont(字体, 字号)  
    设置字体 = 游戏.font.Font("./站酷快乐体.TTF", 字号)  
    设置字体.set_bold(是否加粗)  
    设置字体.set_italic(是否斜体)  
    生成文本 = 设置字体.render(文本, 1, 颜色)  
    屏幕.blit(生成文本, 坐标)
     
def 主函数():
    游戏.init()
    等级 = 1
    升级(等级)
    屏幕尺寸 = (界面宽度,界面高度)
    屏幕 = 游戏.display.set_mode(屏幕尺寸)
    游戏.display.set_caption('贪吃蛇')
    时钟 = 游戏.time.Clock()
    分数 = 0
    是否死亡 = False
    # 字体 = 可用字体(游戏.font.get_fonts())
    字体 = ""
    步数 = 0
    # 蛇/食物
    蛇 = 蛇类()
    食物组 = []
    # 食物 = 食物类()
    目标点 = 目标点类()
    
    for x in range(5):
        食物组.append(食物类())

    while True:
        for 事件 in 游戏.event.get():
            if 事件.type == 游戏.QUIT:
               游戏.quit()
               return
            if 事件.type == 游戏.KEYDOWN:                
                蛇.转向(事件.key)
                目标点.移除()
                # 死后按space重新
                if 事件.key == 游戏.K_SPACE and 是否死亡:
                    return 主函数()
            if 事件.type == 游戏.MOUSEBUTTONDOWN:
                # if(事件.button==3):  #右键
                    x,y=事件.pos
                    目标点.生成(x,y)
                    if x>100 and x<450 and y>360 and y<400 and 是否死亡:
                        目标点.移除()
                        return 主函数()
                
            
        屏幕.fill((255,255,255))
        
        # 画蛇身 / 每一步+1分
        if not 是否死亡:
            # 分数+=1
            步数+=1
            if 目标点.区域.x>0 :
                蛇.自动转向(目标点.区域)
            蛇.移动()
        节=len(蛇.蛇身)

        色差=100/节
        for 区域 in 蛇.蛇身:
            游戏.draw.rect(屏幕,(20,220-节*色差,39+节*色差),区域,0)
            节-=1
            
        # 显示死亡文字
        是否死亡 = 蛇.是否死亡()
        if 是否死亡:
            显示文本(屏幕,(100,200),'你挂了!',(227,29,18),False,100,False,字体)
            显示文本(屏幕,(100,360),'按 空格键 重新开始...',(0,0,22),False,30,False,字体)
            
        # 食物处理 / 吃到+50分
        
        for 食物 in 食物组:
            if 食物.区域 == 蛇.蛇身[0]:
                分数+=50
                食物.移除()
                蛇.增加节点()

        if 目标点.区域 in 蛇.蛇身:
            目标点.移除()
        
        if 分数/200 >= 等级:
            等级+=1
            升级(等级)
            目标点 = 目标点类()
            for 食物 in 食物组:
                食物.刷新()



        for 食物 in 食物组:
            食物.生成()
            游戏.draw.rect(屏幕,(136,0,21),食物.区域,0)
        
        游戏.draw.rect(屏幕,(98,194,213),目标点.区域,0)
        
        # 显示分数文字
        显示文本(屏幕,(50,500),'得分: '+str(分数),(223,223,223),False,60,False,字体)
        显示文本(屏幕,(5,5),'等级: '+str(等级),(123,123,123),False,20,False,字体)
        游戏.display.update()
        时钟.tick(7)
    
if __name__ == '__main__':
    主函数()